﻿using mozhi.smarterp.Business.Enums;
using Mozhi.Abp.Domain.AuthorCenter;
using Mozhi.Abp.Domain.BasicData;
using NPOI.SS.Formula.Functions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Volo.Abp;

namespace mozhi.smarterp.Business.Sales
{
    /// <summary>
    /// 销售出库
    /// </summary>
    public class SaleDelivery : DocumentAggregateRoot<SaleDeliveryItem>
    {
        public Guid CustomerId { get; private set; }

        public Customer Customer { get; private set; }

        /// <summary>
        /// 仓管员
        /// </summary>
        public Guid? WarehouseClerkId { get; private set; }

        /// <summary>
        /// 仓管员
        /// </summary>
        public Employee WarehouseClerk { get; private set; }

        public bool IsCreditNote { get; private set; }

        private SaleDelivery() { }

        public SaleDelivery(Guid id, string number , DateTime date , Customer customer, Currency currency , Department department , Employee warehouseClerk , string comment) 
            : base(id , number , date , false , currency , currency.ExchangeRate , department , comment)
        {
            Customer = customer;
            CustomerId = customer==null ? default : customer.Id;

            WarehouseClerk = warehouseClerk;
            WarehouseClerkId = warehouseClerk?.Id;

            Validate();
        }

        public void Change(DateTime date, Customer customer, Currency currency, Department department, Employee warehouseClerk, string comment)
        {
            Customer = customer;
            CustomerId = Customer == null ? default : Customer.Id;


            Department = department;
            DepartmentId = department?.Id;

            WarehouseClerk = warehouseClerk;
            WarehouseClerkId = warehouseClerk?.Id;

            Currency = currency;
            CurrencyId = currency == null ? default : currency.Id;
            ExchangeRate = currency == null ? 0 : currency.ExchangeRate;

            Date = date;

            Comment = comment;

            Validate();
        }


        #region
        protected override void AddOrUpdateItem(SaleDeliveryItem item)
        {
            if (Status == DocumentStatusType.Approved)
                throw new UserFriendlyException("审核单据不允许修改", "100000");

            if (item.Product.Type != (int)ProductType.Stock)
                throw new UserFriendlyException($"产品：{item.Product.Code}-{item.Product.Name}非库存产品，不允许出库", "100000");

            if(!item.Product.Saleable)
                throw new UserFriendlyException($"产品：{item.Product.Code}-{item.Product.Name}不允许销售", "100000");

            var match = Items.FirstOrDefault(x => x.Id == item.Id);

            if (match == null)
            {
                match = item;

                match.CalculateBaiscUnitQuantity();
                match.CalculateAmount(IncludeTax, ExchangeRate, item.IsGift);

                Items.Add(match);
            }

            else
            {
                match.Change(item.Product, item.AuxiliaryUnit, item.AuxiliaryQuantity, item.AuxiliaryQuantity, item.Price, item.ProductAuxiliaryUnit, item.TaxRate, item.Warehouse, item.LocationId, item.BatchNumber, item.SerialNumber,
                    item.ProductionDate, item.ShelfLifeDays, item.Remark, item.IsGift);

                item.CalculateBaiscUnitQuantity();
                item.CalculateAmount(IncludeTax, ExchangeRate, item.IsGift);

            }
        }

        protected override void Validate()
        {
            base.Validate();
        }

        #endregion
    }

    public class SaleDeliveryItem : DocumentEntity
    {
        public Guid WarehouseId { get; private set; }

        public Warehouse Warehouse { get; private set; }

        public Guid? LocationId { get; private set; }

        public Location Location { get; private set; }

        /// <summary>
        /// 应发数量
        /// </summary>
        public decimal OrderedQuantity { get; private set; }

        public string BatchNumber { get; private set; }

        public string SerialNumber { get; private set; }

        public DateTime? ProductionDate { get; private set; }

        /// <summary>
        /// 保质期（天）
        /// </summary>
        public decimal? ShelfLifeDays { get; private set; }

        /// <summary>
        /// 过期日期
        /// </summary>
        public DateTime? ExpirationDate { get; private set; }

        public bool IsGift {  get; private set; }

        /// <summary>
        /// 成本单价(原币)
        /// </summary>
        public decimal? CostPriceFr { get; private set; }

        public decimal? CostPrice { get; private set; }

        private SaleDeliveryItem() { }

        public SaleDeliveryItem(Guid id, Product product, Unit inventoryUnit, decimal orderedQuantity, decimal deliveredQuantity, decimal price, ProductAuxiliaryUnit productAuxiliaryUnit, TaxRate taxRate, Warehouse warehouse, Guid? locationId,
            string batchNumber, string serialNumber, DateTime? productionDate, decimal? shelfLiftDays, string remark, bool isGift) :
            base(id, product, inventoryUnit, productAuxiliaryUnit, deliveredQuantity, price, taxRate, remark)
        {
            Id = id;

            Warehouse = warehouse;
            WarehouseId = warehouse == null ? default : warehouse.Id;
            LocationId = locationId;

            BatchNumber = batchNumber;
            SerialNumber = serialNumber;
            ProductionDate = productionDate;
            ShelfLifeDays = shelfLiftDays;
            ExpirationDate = productionDate.HasValue && ShelfLifeDays.HasValue ? productionDate.Value.AddDays((double)shelfLiftDays.Value) : null;
            OrderedQuantity = orderedQuantity;

            SetIsGift(isGift);

            Validate();
        }

        public void Change(Product product, Unit inventoryUnit, decimal orderedQuantity, decimal deliveredQuantity, decimal price, ProductAuxiliaryUnit productAuxiliaryUnit, TaxRate taxRate, Warehouse warehouse, Guid? locationId, 
            string batchNumber, string serialNumber, DateTime? productionDate, decimal? shelfLiftDays, string remark , bool isGift)
        {
            base.Change(product, inventoryUnit, productAuxiliaryUnit, deliveredQuantity, price, taxRate, remark);

            Warehouse = warehouse;
            WarehouseId = warehouse==null ? default : warehouse.Id;
            LocationId = locationId;

            BatchNumber = batchNumber;
            SerialNumber = serialNumber;
            ProductionDate = productionDate;
            ShelfLifeDays = shelfLiftDays;
            ExpirationDate = productionDate.HasValue && ShelfLifeDays.HasValue ? productionDate.Value.AddDays((double)shelfLiftDays.Value) : null;
            OrderedQuantity = orderedQuantity;

            SetIsGift(isGift);

            Validate();
        }

        #region
        private void SetIsGift(bool isGift)
        {
            IsGift = isGift;

            if (isGift)
            {
                Price = 0;
                TaxRate = null;
                TaxRateId = null;
                TaxRateValue = null;
            }
        }

        protected override void Validate()
        {
            base.Validate();

            if (Warehouse == null)
                throw new UserFriendlyException("仓库不存在", "100000");

            Warehouse.Validate();
            Warehouse.ValidateLoaction(LocationId);

            if (AuxiliaryUnit == null)
                throw new UserFriendlyException("出库单位不存在", "100000");

            if (AuxiliaryQuantity <= 0)
                throw new UserFriendlyException("应发数量必须大于0", "100000");

            if (!IsGift && Price <= 0)
                throw new UserFriendlyException("单价必须大于0");
        }
        #endregion
    }
}
